import Box2D.b2 as b2
import math
import pyglet
from pyglet.gl import *

import camera
from camera import world_to_pixels, pixels_to_world
import config
from constants import UPDATE_RATE
from constants import STRENGTH_OF_GRAVITY as G
import debug
import mode
import player
import resources


class Menu(mode.Mode):
    name = "menu"

    def __init__(self):
        self.init_graphics()
        self.init_world()
        self.init_player()
        self.selected = 0
        self.entries_pos = (world_to_pixels(-10),
                            world_to_pixels(-2))

        self.create_entries(("Continue", lambda: self.control.switch_handler("level_transition")),
                            ("Start anew", self.new_game),
                            ("Quit", lambda: pyglet.app.exit()))


    def connect(self, control):
        self.control = control
        self.window = control.window

        resources.play_music("menu.mp3", self.control.musicplayer)

    def new_game(self):
        resources.set_level(0)
        self.control.switch_handler("level_transition")

    def init_player(self):
        # Load images
        player_image = resources.image("player.png", (0.5, 0), flip_x=True)
        pendulum_image = resources.image("player_pend.png", (0.5, 1))

        # Define scale
        scale = 10

        # Create sprites
        self.player_sprite = pyglet.sprite.Sprite(player_image, x=300, y=-250,
                                                  batch=self.batch_dynamic)
        self.pendulum_sprite = pyglet.sprite.Sprite(pendulum_image, x=0, y=0,
                                                  batch=self.batch_below_dynamic)

        self.player_sprite.scale = scale
        self.pendulum_sprite.scale = scale

        self.joint_pos = b2.vec2(pixels_to_world(self.player_sprite.x),
                                 (pixels_to_world(self.player_sprite.y +
                                                  self.player_sprite.height -
                                                  self.player_sprite.width/2.0)))

        self.pendulum_body = self.world.CreateDynamicBody(
            position=self.joint_pos,
            angle=2*math.pi/3)

        self.pendulum_fixture = self.pendulum_body.CreatePolygonFixture(
            box=(pixels_to_world(self.pendulum_sprite.width/2.0),
                 pixels_to_world(1.5),
                 (0, -pixels_to_world(11*scale)),
                 0),
            density=0.01,
            userData={"self":self})

        # Create a joint for the pendulum (and a static body for it to
        # be joined with).
        self.static_body = self.world.CreateStaticBody()
        self.pendulum_joint = self.world.CreateRevoluteJoint(
            bodyA = self.static_body,
            bodyB = self.pendulum_body,
            anchor = self.pendulum_body.position)

    def init_graphics(self):
        glDisable(GL_DEPTH_TEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        self.camera = camera.Camera((0, 0), scale=2)

        self.batch_static = pyglet.graphics.Batch()
        self.batch_below_dynamic = pyglet.graphics.Batch()
        self.batch_dynamic = pyglet.graphics.Batch()
        self.batch_foreground = pyglet.graphics.Batch()

        self.background = pyglet.resource.image("background.jpg")
        self.background.anchor_x = self.background.width / 2
        self.background.anchor_y = self.background.height / 2

        logoimg = resources.image("logotype.png", (0.5, 0.5), antialiasing=True)

        self.logo = pyglet.sprite.Sprite(logoimg,
                                         world_to_pixels(-9),
                                         world_to_pixels(7))

    def init_world(self):
        self.world = b2.world(gravity=(0, 0), doSleep=False)

        if config.debug:
            self.renderer = debug.PygletDraw(None)
            self.world.renderer = self.renderer

            self.renderer.flags = dict(
                drawShapes=True,
                drawJoints=True,
                drawAABBs=False,
                drawPairs=True,
                #drawCOMs  =True,
                # The following is only applicable when using b2DrawExtended.
                # It indicates that the C code should transform box2d coords to
                # screen coordinates.

                convertVertices=isinstance(self.renderer, b2.drawExtended))

            self.renderer.batch = pyglet.graphics.Batch()


    def create_entries(self, *entries):
        self.entries = []
        y = self.entries_pos[1]
        for (s, function) in entries:
            l = pyglet.text.Label(text=s,
                                  font_size=30,
                                  color=(0x3F, 0x3F, 0x3F, 255),
                                  x=self.entries_pos[0], y=y)
            y -= l.content_height
            self.entries.append((l, function))
        self.select(0)

    def disconnect(self):
        self.control.musicplayer.pause()

    def update_sprites(self):
        try:
            self.pendulum_sprite.x = world_to_pixels(self.pendulum_body.position[0])
            self.pendulum_sprite.y = world_to_pixels(self.pendulum_body.position[1])

            self.pendulum_sprite.rotation = (-self.pendulum_body.angle) * (180 / math.pi)
        except AttributeError:
            pass

    def update(self, dt):
        try:
            self.pendulum_body.ApplyForce(G * self.pendulum_body.mass * b2.vec2(0, -1),
                                          self.pendulum_body.worldCenter)
        except AttributeError:
            pass
        self.world.Step(1 / UPDATE_RATE, 10, 10)
        self.update_sprites()

    def select(self, diff):
        self.entries[self.selected][0].color = (0x3F, 0x3F, 0x3F, 255)
        self.selected = (self.selected + diff) % len(self.entries)
        self.entries[self.selected][0].color = (255, 255, 255, 255)

    def on_key_press(self, key, mods):
        if key == pyglet.window.key.UP:
            self.select(-1)
        if key == pyglet.window.key.DOWN:
            self.select(+1)
        if key == pyglet.window.key.F11:
            self.window.set_fullscreen(not self.window.fullscreen)
        elif key == pyglet.window.key.RETURN:
            self.entries[self.selected][1]()

    def on_key_release(self, key, mods):
        pass

    def on_draw(self):
        self.window.clear()
        self.camera.focus(self.window.width, self.window.height)

        glColor3f(1.0, 1.0, 1.0)
        self.background.blit(0, 0)

        self.batch_static.draw()
        self.batch_below_dynamic.draw()
        self.batch_dynamic.draw()
        self.batch_foreground.draw()

        for entry in self.entries:
            entry[0].draw()

        self.logo.draw()

        if config.debug:
            #glLineWidth(1)

            glMatrixMode(GL_MODELVIEW)
            glPushMatrix()
            glMatrixMode(GL_PROJECTION)
            glPushMatrix()

            self.renderer.batch.draw()

            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
            glPopMatrix()


mode.modes["menu"] = Menu
